﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using DynORM.Interfaces;
using DynORM.Mappers;
using DynORM.Enums;
using DynORM;
using DynORM.ValueObjects;
using DynORM.ReferenceObjects;
using System.Xml.Serialization;
using System.Xml;
using System.IO;

namespace UnitTests.DAL
{
    [TestClass]
    public class CheckIntegrityUnitTests
    {
        private IFieldDescriptor GenerateNewFieldDescriptor(Type type, string name)
        {
            return new FieldDescriptor(type, name);
        }

        [TestMethod]
        public void FieldDescriptorCheckIntegrityTest()
        {
            CheckIntegrityResult cir = new CheckIntegrityResult(true, String.Empty);
            IFieldDescriptor fd = GenerateNewFieldDescriptor(typeof(Guid), "Id");
            Assert.AreEqual<CheckIntegrityResult>(cir, fd.CheckStructureIntegrity(true));
        }

        private IField GenerateNewField(Type type, string name, object value)
        {
            return new Field(type, name, value);
        }

        [TestMethod]
        public void FieldCheckIntegrityTest()
        {
            CheckIntegrityResult cir = new CheckIntegrityResult(true, String.Empty);
            IField f = GenerateNewField(typeof(Guid), "Id", Guid.NewGuid());
            Assert.AreEqual<CheckIntegrityResult>(cir, f.CheckValuesIntegrity(true));
        }

        [TestMethod]
        public void FieldCheckIntegrityTest2()
        {
            CheckIntegrityResult cir = new CheckIntegrityResult(true, String.Empty);
            IField f = GenerateNewField(typeof(Guid), "Id", DateTime.MinValue);
            Assert.AreNotEqual<CheckIntegrityResult>(cir, f.CheckValuesIntegrity(true));
        }

        private IPrimaryKeyDescriptor GenerateNewPrimaryKeyDescriptor(string tablename, string fieldname1, string fieldname2)
        {
            IFieldDescriptor fd1 = GenerateNewFieldDescriptor(typeof(Guid), fieldname1);
            IFieldDescriptor fd2 = GenerateNewFieldDescriptor(typeof(Guid), fieldname2);
            Dictionary<int, IFieldDescriptor> fds = new Dictionary<int, IFieldDescriptor>();
            fds.Add(0, fd1);
            fds.Add(1, fd2);
            return new PrimaryKeyDescriptor(tablename, fds, tablename + "_PK");
        }

        [TestMethod]
        public void PrimaryKeyDescriptorCheckIntegrityTest()
        {
            CheckIntegrityResult cir = new CheckIntegrityResult(true, String.Empty);
            IPrimaryKeyDescriptor pk = GenerateNewPrimaryKeyDescriptor("Test1", "RowID_1", "RowID_2");
            Assert.AreEqual<CheckIntegrityResult>(cir, pk.CheckStructureIntegrity(true));
        }


        private IPrimaryKey GenerateNewPrimaryKey(string tablename, string fieldname1, string fieldname2, object value1, object value2)
        {
            IField f1 = GenerateNewField(typeof(Guid), fieldname1, value1);
            IField f2 = GenerateNewField(typeof(Guid), fieldname2, value2);
            Dictionary<int, IField> fs = new Dictionary<int, IField>();
            fs.Add(0, f1);
            fs.Add(1, f2);
            return new PrimaryKey(tablename, fs, tablename + "_PK");
        }

        [TestMethod]
        public void PrimaryKeyCheckIntegrityTest()
        {
            CheckIntegrityResult cir = new CheckIntegrityResult(true, String.Empty);
            IPrimaryKey pk = GenerateNewPrimaryKey("Test1", "RowID_1", "RowID_2", Guid.NewGuid(), Guid.NewGuid());
            Assert.AreEqual<CheckIntegrityResult>(cir, pk.CheckValuesIntegrity(true));
        }

        [TestMethod]
        public void PrimaryKeyCheckIntegrityTest2()
        {
            CheckIntegrityResult cir = new CheckIntegrityResult(true, String.Empty);
            IPrimaryKey pk = GenerateNewPrimaryKey("Test1", "RowID_1", "RowID_2", 1, 2);
            Assert.AreNotEqual<CheckIntegrityResult>(cir, pk.CheckValuesIntegrity(true));
        }

        private IForeignKeyDescriptor GenerateNewForeignKeyDescriptor(string tablename, string reltablename, string fieldname1, string fieldname2)
        {
            IFieldDescriptor fd1 = GenerateNewFieldDescriptor(typeof(Guid), fieldname1);
            IFieldDescriptor fd2 = GenerateNewFieldDescriptor(typeof(Guid), fieldname2);
            Dictionary<int, IFieldDescriptor> fds = new Dictionary<int, IFieldDescriptor>();
            fds.Add(0, fd1);
            fds.Add(1, fd2);
            return new ForeignKeyDescriptor(tablename, fds, reltablename, fds, tablename + "_" + reltablename + "_FK");
        }

        [TestMethod]
        public void ForeignKeyDescriptorCheckIntegrityTest()
        {
            CheckIntegrityResult cir = new CheckIntegrityResult(true, String.Empty);
            IForeignKeyDescriptor fk = GenerateNewForeignKeyDescriptor("Test1", "RelTest1", "Test1_RelTest1_FK_FRowID_1", "Test1_RelTest1_FK_FRowID_2");
            Assert.AreEqual<CheckIntegrityResult>(cir, fk.CheckStructureIntegrity(true));
        }

        private IForeignKey GenerateNewForeignKey(string tablename, string reltablename, string fieldname1, string fieldname2, object value1, object value2)
        {
            IField f1 = GenerateNewField(typeof(Guid), fieldname1, value1);
            IField f2 = GenerateNewField(typeof(Guid), fieldname2, value2);
            Dictionary<int, IField> fs = new Dictionary<int, IField>();
            fs.Add(0, f1);
            fs.Add(1, f2);
            return new ForeignKey(tablename, fs, reltablename, fs, tablename + "_" + reltablename + "_FK");
        }

        [TestMethod]
        public void ForeignKeyCheckIntegrityTest()
        {
            CheckIntegrityResult cir = new CheckIntegrityResult(true, String.Empty);
            IForeignKey fk = GenerateNewForeignKey("Test1", "RelTest1", "Test1_RelTest1_FK_FRowID_1", "Test1_RelTest1_FK_FRowID_2", Guid.NewGuid(), Guid.NewGuid());
            Assert.AreEqual<CheckIntegrityResult>(cir, fk.CheckValuesIntegrity(true));
        }

        private IRowDescriptor GenerateNewRowDescriptor(string tableName, Type pkFieldType, string pkFieldName, Type fieldType, string fieldName)
        {
            Dictionary<int, IFieldDescriptor> pkFieldDescs = new Dictionary<int, IFieldDescriptor>();
            pkFieldDescs.Add(0, GenerateNewFieldDescriptor(pkFieldType, pkFieldName));
            PrimaryKeyDescriptor pkd = new PrimaryKeyDescriptor(tableName, pkFieldDescs, tableName + "_PK");
            List<IFieldDescriptor> fieldDescs = new List<IFieldDescriptor>();
            fieldDescs.Add(GenerateNewFieldDescriptor(fieldType, fieldName));
            return new RowDescriptor(tableName, fieldDescs, new List<IRelationDescriptor>() { pkd });
        }

        [TestMethod]
        public void RowDescriptorCheckIntegrityTest()
        {
            CheckIntegrityResult cir = new CheckIntegrityResult(true, String.Empty);
            IRowDescriptor rd = GenerateNewRowDescriptor("Test1", typeof(Guid), "RowID", typeof(DateTime), "DateInfo");
            Assert.AreEqual<CheckIntegrityResult>(cir, rd.CheckStructureIntegrity(true));
        }

        private IRow GenerateNewRow(string tableName, Type pkFieldType, string pkFieldName, object pkValue, Type fieldType, string fieldName, object value)
        {
            Dictionary<int, IField> pkField = new Dictionary<int, IField>();
            pkField.Add(0, GenerateNewField(pkFieldType, pkFieldName, pkValue));
            PrimaryKey pk = new PrimaryKey(tableName, pkField, tableName + "_PK");
            List<IField> fields = new List<IField>();
            fields.Add(GenerateNewField(fieldType, fieldName, value));
            return new Row(fields, new List<IRelation>() { pk });
        }

        [TestMethod]
        public void RowCheckIntegrityTest()
        {
            CheckIntegrityResult cir = new CheckIntegrityResult(true, String.Empty);
            IRow r = GenerateNewRow("Test1", typeof(Guid), "RowID", Guid.NewGuid(), typeof(DateTime), "DateInfo", DateTime.Now);
            Assert.AreEqual<CheckIntegrityResult>(cir, r.CheckValuesIntegrity(true));
        }

    }
}
